﻿//========================================
// All rights reserved (C) 2017-2100
// CLR 版本：	4.0.30319.42000
// 命名空间:	SFJDService
// 文 件 名：	EventBus
// 作    者：	WooG
// 联系方式：	wooglle@163.com
// 创建时间：	2018/4/25 23:30:06
//========================================
using SFJDService.EventHandle;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;

namespace SFJDService.EventHandle
{
    public class EventBus
    {
        //public event SCPopupHandler SCEventPopup;
        //public delegate void SCPopupHandler(string title, string message);
        public static EventBus instance => new EventBus();
        private readonly ConcurrentDictionary<Type, List<Type>> eventHandlerMap;

        public EventBus()
        {
            eventHandlerMap = new ConcurrentDictionary<Type, List<Type>>();
            MapEvent2Handler();
        }

        /// <summary>
        /// 通过反射将 事件源 与 事件处理 绑定
        /// </summary>
        private void MapEvent2Handler()
        {
            //Assembly assembly = Assembly.GetEntryAssembly();
            Assembly assembly = Assembly.GetAssembly(typeof(EventBus));
            foreach (var type in assembly.GetTypes())
            {
                if (typeof(IEventHandler).IsAssignableFrom(type))//判断当前类型是否实现了IEventHandler接口
                {
                    Type handlerInterface = type.GetInterface("IEventHandler`1");//获取该类实现的泛型接口
                    if(handlerInterface != null)
                    {
                        Type eventDataType = handlerInterface.GetGenericArguments()[0];// 获取泛型接口指定的参数类型

                        if (eventHandlerMap.ContainsKey(eventDataType))
                        {
                            List<Type> handlerTypes = eventHandlerMap[eventDataType];
                            handlerTypes.Add(type);
                            eventHandlerMap[eventDataType] = handlerTypes;
                        }
                        else
                        {
                            var handlerTypes = new List<Type> { type };
                            eventHandlerMap[eventDataType] = handlerTypes;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 手动绑定
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventHandler"></param>
        public void Register<TEventData>(Type eventHandler)
        {
            List<Type> handlerTypes = eventHandlerMap[typeof(TEventData)];
            if (!handlerTypes.Contains(eventHandler))
            {
                handlerTypes.Add(eventHandler);
                eventHandlerMap[typeof(TEventData)] = handlerTypes;
            }
        }

        /// <summary>
        /// 手动解除绑定
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventHandler"></param>
        public void UnRegister<TEventData>(Type eventHandler)
        {
            List<Type> handlerTypes = eventHandlerMap[typeof(TEventData)];
            if (handlerTypes.Contains(eventHandler))
            {
                handlerTypes.Remove(eventHandler);
                eventHandlerMap[typeof(TEventData)] = handlerTypes;
            }
        }

        /// <summary>
        /// 根据事件源 触发 绑定的事件处理器
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventData"></param>
        public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData
        {
            List<Type> handlers = eventHandlerMap[eventData.GetType()];

            if(handlers != null && handlers.Count > 0)
            {
                foreach(var handler in handlers)
                {
                    MethodInfo method = handler.GetMethod("HandleEvent");
                    if(method != null)
                    {
                        object obj = Activator.CreateInstance(handler);
                        method.Invoke(obj, new object[] { eventData });
                    }
                }
            }
        }
    }
}
